package com.lanlengran.plugintest

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.AssetManager
import android.content.res.Resources
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import dalvik.system.PathClassLoader
import java.io.*
import java.nio.channels.FileChannel

class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity"
        private const val REQUEST_CODE = 0x99
        private const val PLUGIN_PATH = "/sdcard/pluginTest/test.apk"
    }

    val plugin1=PluginTarget("/sdcard/pluginTest/test.apk","com.example.myworktest.MainActivity")
    val plugin2=PluginTarget("/sdcard/pluginTest/test2.apk","com.motorola.plugin.TimeWeatherPlugin")
    val loadPlugin=plugin1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var classloader = classLoader
        while (classloader != null) {
            Log.d(TAG, "onCreate: $classloader")
            classloader = classloader.parent
        }

        if (PackageManager.PERMISSION_DENIED == ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_EXTERNAL_STORAGE
            )
        ) {
            requestPermissions(
                arrayOf(
                    Manifest.permission.READ_EXTERNAL_STORAGE
                ),
                REQUEST_CODE
            )
            return
        }

    }
    public fun startTest(view: View) {
        when(view.id){
            R.id.add_plugin->{
                startPluginTest()
            }
            R.id.add_local_view->{
                val pluginContainer = findViewById<FrameLayout>(R.id.plugin_container)
                pluginContainer.removeAllViews()
                pluginContainer.addView( LayoutInflater.from(this).inflate(R.layout.plugin_test_layout,null,false))

            }
        }
    }
    public fun startPluginTest() {
        try {
//            var pluginFile=File(getFilesDir()?.absolutePath+"/test.apk")
//            if (true){
//               // val file = File("/data/app/~~XBRvz5uOqhgydVdKHpi5ag==/com.lanlengran.plugintest-HIGGTjhj4ybS5f9e1CGYag==/base.apk")
//                val file = File("/sdcard/pluginTest/test.apk")
//                copyFile(file,pluginFile.absolutePath)
//            }


            var pluginFile = File(loadPlugin.path)
            Log.d(TAG, "pluginFile.getPath()==> ${pluginFile.absolutePath}")
            Log.d(TAG, "startTest:$pluginFile.exists==> ${pluginFile.exists()}")
            Log.d(TAG, "startTest:file.canRead==> ${pluginFile.canRead()}")
            Log.d(TAG, "startTest:file.canExecute==> ${pluginFile.canExecute()}")

            val classLoader = PathClassLoader(
                pluginFile.absolutePath, classLoader.parent
            )

            val pluginMainActClazz = classLoader.loadClass(loadPlugin.classPath)
            val pluginMainActivity = pluginMainActClazz.newInstance()
            addPluginView(
                pluginFile.absolutePath,
                classLoader,
                pluginMainActClazz!!,
                pluginMainActivity!!
            )
//            val BundleClazz = classLoader.loadClass("android.os.Bundle")
//            val method = pluginMainActClazz.getDeclaredMethod("onCreate",Bundle::class.java)
//            method.isAccessible=true
//            method.invoke(pluginMainActivity,null)
//            pluginMainActivity.sayHello()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun addPluginView(
        apkPath: String,
        classLoader: ClassLoader,
        pluginMainActClazz: Class<*>,
        pluginMainActivity: Any
    ) {
        try{
            val onCreateViewMethod =
                pluginMainActClazz.getMethod("onCreateView", LayoutInflater::class.java,
                    ViewGroup::class.java
                )
            val pluginContext = PluginContext(this);
            val assentManager = AssetManager::class.java.newInstance()
            val method = AssetManager::class.java.getMethod("addAssetPath", String::class.java)
            method.invoke(assentManager, apkPath)
            val resources = Resources(assentManager, resources.displayMetrics, resources.configuration)
            pluginContext.mResources = resources
            pluginContext.mClassLoader = classLoader
//        val layoutInflater = PluginLayoutInflater(LayoutInflater.from(pluginContext),pluginContext)
            val layoutInflater = PluginLayoutInflater(pluginContext)
//        layoutInflater.factory2=LayoutInflater.from(this).factory2
//        layoutInflater.setPrivateFactory

            val pluginContainer = findViewById<FrameLayout>(R.id.plugin_container)
            val view = onCreateViewMethod.invoke(pluginMainActivity, layoutInflater,pluginContainer) as View


            pluginContainer.removeAllViews()
            pluginContainer.addView(view)
        }catch (e:Exception){
            e.printStackTrace()
        }

    }

    fun copyFile(src: File?, destPath: String?): Boolean {
        var result = false
        if (src == null || destPath == null) {
            return result
        }
        val dest = File(destPath)
        if (dest != null && dest.exists()) {
            dest.delete() // delete file
        }
        try {
            dest.createNewFile()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        var srcChannel: FileChannel? = null
        var dstChannel: FileChannel? = null
        try {
            srcChannel = FileInputStream(src).getChannel()
            dstChannel = FileOutputStream(dest).getChannel()
            srcChannel.transferTo(0, srcChannel.size(), dstChannel)
            result = true
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
            return result
        } catch (e: IOException) {
            e.printStackTrace()
            return result
        }
        try {
            srcChannel.close()
            dstChannel.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            REQUEST_CODE -> {
                if ((grantResults.isNotEmpty() &&
                            grantResults[0] == PackageManager.PERMISSION_GRANTED)
                ) {

                } else {
                    requestPermissions(
                        arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                        REQUEST_CODE
                    )
                }
                return
            }
        }
    }

}